package com.example.likestarlibrary;

import com.example.likestarlibrary.util.AnimatorValueUtil;
import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.render.Path;
import ohos.agp.render.PathMeasure;
import ohos.agp.utils.Matrix;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;

import java.util.HashMap;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 飘心路径动画器
 */
public class TCPathAnimator extends TCAbstractPathAnimator {
    private final static String TAG = "TCPathAnimator";
    //路径的缓存
    private final static int MAX_PATH_COUNTS = 10;      //最多生成的路径数目
    private final AtomicInteger mCounter = new AtomicInteger(0);
    // 随机数
    final double val = Math.random();
    final int sval = (int)(val*10);
    private EventHandler mHandler;
    private int mCurrentPathCounts = 0;                 //已经生成的路径数目
    private HashMap<Integer, Path> mPathVec = null;     //已经生成的路径缓存
    public TCPathAnimator(Config config) {
        super(config);
        mHandler = new EventHandler(EventRunner.getMainEventRunner());
        mPathVec = new HashMap<>();
    }

    private static float scale(double a, double b, double c, double d, double e) {
        return (float) ((a - b) / (c - b) * (e - d) + d);
    }

    @Override
    public void start(final Component child, final ComponentContainer parent) {
        //默认会在顶部显示一次，所以先隐藏掉，等动画开始再显示
        child.setVisibility(Component.HIDE);
        parent.addComponent(child, new ComponentContainer.LayoutConfig(mConfig.heartWidth, mConfig.heartHeight));

        Path path;
        ++mCurrentPathCounts;

        //如果已经生成的路径数目超过最大设定，就从路径缓存中随机取一个路径用于绘制，否则新生成一个
        if (mCurrentPathCounts > MAX_PATH_COUNTS) {
            path = mPathVec.get(Math.abs(sval % MAX_PATH_COUNTS) + 1);
        } else {
            path = createPath(mCounter, parent, 2);
            mPathVec.put(mCurrentPathCounts, path);
        }

        FloatAnimationn anim = new FloatAnimationn(path, randomRotation(), parent, child);
        anim.setDuration(mConfig.animDuration);
        anim.setCurveType(Animator.CurveType.LINEAR);
        anim.setStateChangedListener(new Animator.StateChangedListener() {
            @Override
            public void onStart(Animator animator) {
                mCounter.incrementAndGet();
            }

            @Override
            public void onStop(Animator animator) {

            }

            @Override
            public void onCancel(Animator animator) {

            }

            @Override
            public void onEnd(Animator animator) {
                mHandler.postTask(() -> parent.removeComponent(child));
                mCounter.decrementAndGet();
            }

            @Override
            public void onPause(Animator animator) {

            }

            @Override
            public void onResume(Animator animator) {

            }
        });
        anim.start();
    }

    static class FloatAnimationn extends AnimatorValue {
        private PathMeasure mPm;
        private Component mView;
        private float mDistance;
        private float mRotation;
        private AnimatorValueUtil animatorValueUtil;

        public FloatAnimationn(Path path, float rotation, Component parent, Component child) {
            mPm = new PathMeasure(path, false);
            mDistance = mPm.getLength();
            mView = child;
            mView.setClipEnabled(false);
            mRotation = rotation;
            animatorValueUtil = new AnimatorValueUtil();
            animatorValueUtil.ofFloat(0, -1, 1, -1);
            setValueUpdateListener((animatorValue, v) -> {
                mView.setVisibility(Component.VISIBLE);
                doAnim(v);
            });
        }

        private void doAnim(float factor) {
            float[] floats = new float[]{1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f};
            Matrix matrix = new Matrix(floats);
            mPm.getMatrix(mDistance * factor, matrix, PathMeasure.GET_POSITION_MATRIX_FLAG);
            // 根据PathMeasure测量path路径的所有坐标，按照坐标进行位移
            float[] pos = new float[2];
            float[] tan = new float[2];
            mPm.getPosTan(mDistance * factor, pos, tan);
            System.out.println("------------------" + pos[1]);
            mView.setTranslation(animatorValueUtil.getValue(factor) * 25, (pos[1]));
            //设置旋转范围
            mView.setRotation(mRotation * factor);
            //自定义算法
            float scale = 1F;
            if (3000.0F * factor < 200.0F) {
                scale = scale(factor, 0.0D, 0.06666667014360428D, 0.20000000298023224D, 1.100000023841858D);
            } else if (3000.0F * factor < 300.0F) {
                scale = scale(factor, 0.06666667014360428D, 0.10000000149011612D, 1.100000023841858D, 1.0D);
            }
            //设置缩放范围
            mView.setScaleX(scale);
            mView.setScaleY(scale);
            //透明度
            mView.setAlpha(1.0f - factor);
        }
    }
}

